package com.hzw.saas.service.ds.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.ds.IHeartbeatService;
import com.hzw.saas.api.ds.bo.HeartbeatBo;
import com.hzw.saas.api.ds.query.HeartbeatQuery;
import com.hzw.saas.common.config.util.RedisUtil;
import com.hzw.saas.common.util.MapperUtil;
import com.hzw.saas.common.util.SnowFlakeUtil;
import com.hzw.saas.common.util.constants.CacheConsts;
import com.hzw.saas.service.ds.mapper.HeartbeatMapper;
import com.hzw.saas.service.ds.model.Heartbeat;
import com.hzw.saas.service.ds.model.HeartbeatLog;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Optional;

@Service
public class HeartbeatServiceImpl extends ServiceImpl<HeartbeatMapper, Heartbeat> implements IHeartbeatService, IService<Heartbeat> {

    @Resource
    private HeartbeatLogServiceImpl heartbeatLogService;
    @Resource
    private OnlineLevelInfoServiceImpl onlineLevelInfoService;

    @Override
    @Transactional
    public HeartbeatBo heartbeat(HeartbeatQuery heartbeatQuery) {

        RedisUtil.set(CacheConsts.KEY_DS_HEARTBEAT_INTERVAL, heartbeatQuery.getInterval(), heartbeatQuery.getInterval() * 2);
        LocalDateTime now = LocalDateTime.now();

        // 初始化log记录, 留空parentId, 不同处理
        HeartbeatLog heartbeatLog = MapperUtil.nf().map(heartbeatQuery, HeartbeatLog.class);
        heartbeatLog.setPid(SnowFlakeUtil.nextIdStr());

        // 根据 logId 查询处理[心跳log表]
        heartbeatLogService.lambdaQuery()
                .eq(HeartbeatLog::getParentId, heartbeatQuery.getLogId())
                .ge(HeartbeatLog::getCreateTime, now.minusSeconds(heartbeatQuery.getInterval() * 2))
                .orderByDesc(HeartbeatLog::getCreateTime)
                .last(" limit 1")
                .oneOpt()
                .orElseGet(() -> {
                    heartbeatQuery.setLogId(heartbeatLog.getPid());
                    return null;
                });
        heartbeatLog.setParentId(heartbeatQuery.getLogId());
        heartbeatLogService.save(heartbeatLog);

        // 根据用户 查询 处理[心跳表]
        super.lambdaQuery()
                .eq(Heartbeat::getUserId, heartbeatQuery.getUserId())
                .eq(Heartbeat::getClientType, heartbeatQuery.getClientType())
                .last(" limit 1")
                .oneOpt()
                .flatMap(heartbeat -> {
                    // [心跳表] 有数据
                    if (heartbeat.getEndTime().isAfter(now.minusSeconds(heartbeatQuery.getInterval() * 2)) && heartbeat.getCheckStatus() == 0) {
                        // 心跳内
                        heartbeat.setEndTime(now);
                    } else {
                        // 有数据 但是断了心跳
                        // 插入等级记录表, 并*计算相应等级和经验*
                        heartbeat = onlineLevelInfoService.processLevel(heartbeat);
                        // 重置 [心跳表]
                        heartbeat.setStartTime(now);
                        heartbeat.setEndTime(now);
                        heartbeat.setCheckStatus(0);
                    }
                    super.updateById(heartbeat);
                    return Optional.of(heartbeat);
                })
                .orElseGet(() -> {
                    // [心跳表] 无数据
                    Heartbeat addHeartbeat = MapperUtil.nf().map(heartbeatQuery, Heartbeat.class);
                    addHeartbeat.setStartTime(now);
                    addHeartbeat.setEndTime(now);
                    addHeartbeat.setPid(SnowFlakeUtil.nextIdStr());
                    super.save(addHeartbeat);
                    return addHeartbeat;
                });


        return new HeartbeatBo()
                .setLogId(heartbeatLog.getParentId());

    }
}
